package com.bz.sso.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bz.dto.CartDto;
import com.bz.mapper.TbUserMapper;
import com.bz.pojo.TbUser;
import com.bz.sso.feign.CommonRedisFeignClient;
import com.bz.sso.service.SSOService;
import com.bz.utils.Builder;
import com.bz.utils.CookieUtils;
import com.bz.utils.MD5Utils;
import com.bz.utils.Result;
import com.bz.vo.CartItemVo;
import com.bz.vo.LoginVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;

@Slf4j
@Service
public class SSOServiceImpl implements SSOService {

    @Autowired
    private CommonRedisFeignClient commonRedisFeignClient;
    @Autowired
    private TbUserMapper tbUserMapper;
    @Autowired
    private ObjectMapper objectMapper;

    private String cart_cookie_name = "cart:cookie:name";

    /**
     * 对用户的注册信息(用户名与电话号码)做数据校验
     * @param checkValue
     * @param checkFlag
     * @return
     */
    @Override
    public Result checkUserInfo(String checkValue, Integer checkFlag) {
        QueryWrapper<TbUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(checkFlag == 1,TbUser::getUsername,checkValue)
            .eq(checkFlag == 2,TbUser::getPhone,checkValue);
        Integer count = tbUserMapper.selectCount(queryWrapper);
        if (count > 0){
            return Result.error("已存在");
        }
        return Result.ok();
    }

    /**
     * 用户注册
     * @param tbUser
     * @return
     */
    @Override
    public Result userRegister(TbUser tbUser) {
        Date date = new Date();
        tbUser.setPassword(MD5Utils.digest(tbUser.getPassword()));
        tbUser.setCreated(date);
        tbUser.setUpdated(date);
        int result = tbUserMapper.insert(tbUser);
        if (result > 0){
            return Result.ok();
        }
        return Result.error("注册失败");
    }

    /**
     * 用户登录
     * @param username
     * @param password
     * @param request
     * @param response
     * @return
     */
    @Override
    public Result userLogin(String username, String password, HttpServletRequest request, HttpServletResponse response) {
        // 1.根据用户名密码查询数据库
        QueryWrapper<TbUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(username != null,TbUser::getUsername,username);
        TbUser tbUser = tbUserMapper.selectOne(queryWrapper);
        if (tbUser == null || !Objects.equals(MD5Utils.digest(password), tbUser.getPassword())){
            return Result.error("用户名或密码有误，请重新输入");
        }
        String token = UUID.randomUUID().toString();
        // 2.将用户添加到Redis中
        this.insertUserToRedis(tbUser, token);
        // 3.将临时购物车中的商品同步到永久购物车中
        this.syncCart(tbUser.getId(),request);
        // 4.删除临时购物车
        this.deleteCookieCart(request,response);
        return Result.ok(Builder.of(LoginVo::new)
                .with(LoginVo::setToken,token)
                .with(LoginVo::setUserid,tbUser.getId().toString())
                .with(LoginVo::setUsername,tbUser.getUsername())
                .build());
    }

    /**
     * 用户退出登录
     * @param token
     * @return
     */
    @Override
    public Result logOut(String token) {
        commonRedisFeignClient.logout(token);
        return Result.ok();
    }

    /**
     * 4.删除临时购物车
     */
    private void deleteCookieCart(HttpServletRequest request,HttpServletResponse response){
        CookieUtils.deleteCookie(request,response,this.cart_cookie_name);
    }

    /**
     * 3.同步购物车
     */
    private void syncCart(Long userid,HttpServletRequest request){
        //获取临时购物车
        CartDto cookieCartDto = this.getCart(request);
        //获取永久购物车
        CartDto redisCartDto = this.getCart(userid);
        //删除永久购物车中所包含临时购物车中的商品
        Map<String, CartItemVo> cookieCartItemVoMap = cookieCartDto.getCartItemVoMap();
        Map<String, CartItemVo> redisCartItemVoMap = redisCartDto.getCartItemVoMap();
        Set<String> keys = cookieCartItemVoMap.keySet();
        for (String key : keys){
            redisCartItemVoMap.remove(key);
        }
        //将同步后的购物车缓存到redis中
        redisCartItemVoMap.putAll(cookieCartItemVoMap);
        //将永久购物车重新缓存到redis中
        commonRedisFeignClient.insertCart(redisCartDto);
    }

    /**
     * 获取临时购物车
     * @param request
     * @return
     */
    private CartDto getCart(HttpServletRequest request){
        // 获取临时购物车
        String cartJson = CookieUtils.getCookieValue(request, cart_cookie_name, true);
        if (cartJson == null || "".equals(cartJson)){
            return new CartDto();
        }
        //如果含有临时购物车，那么需要做json转换
        try {
            return objectMapper.readValue(cartJson, CartDto.class);
        } catch (IOException e) {
            log.error("【解析临时购物车数据失败】,{},{}",cartJson,e);
        }
        return new CartDto();
    }

    /**
     * 获取永久购物车
     * @param userid
     * @return
     */
    private CartDto getCart(Long userid){
        try {
            return commonRedisFeignClient.selectCartByUserId(userid);
        } catch (Exception e) {
            log.error("【获取redis缓存购物车数据失败】, {}",e);
        }
        return new CartDto();
    }

    /**
     * 2.将用户添加到Redis中
     */
    private Integer insertUserToRedis(TbUser tbUser,String userToken){
        try{
            this.commonRedisFeignClient.insertUser(tbUser,userToken);
            return 200;
        }catch(Exception e){
            log.error("【用户登录成功，添加缓存失败】，{}",e);
        }
        return 500;
    }
}
